import { useContext, useMemo, useState } from 'react';
import { ErrorBoundaryContext } from './ErrorBoundaryContext';

import type { UseErrorBoundaryApi, UseErrorBoundaryState } from './types';

export function useErrorBoundary<T = any>(): UseErrorBoundaryApi<T> {
  const context = useContext(ErrorBoundaryContext);

  if (!context) {
    throw new Error(
      'useErrorBoundary must be used within a ErrorBoundaryContextProvider',
    );
  }

  if (
    typeof context.hasError !== 'boolean' ||
    typeof context.resetErrorBoundary !== 'function'
  ) {
    throw new Error('ErrorBoundaryContext not found');
  }

  const [state, setState] = useState<UseErrorBoundaryState<T>>({
    error: null,
    hasError: false,
  });

  const memoized = useMemo(
    () => ({
      resetBoundary: () => {
        context.resetErrorBoundary();
        setState({ error: null, hasError: false });
      },
      showBoundary: (error: T) =>
        setState({
          error,
          hasError: true,
        }),
    }),
    [context.resetErrorBoundary],
  );

  if (state.hasError) {
    throw state.error;
  }

  return memoized;
}
